#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "HistComparisonAlgorithm.h"

double HistComparisonAlgorithm::getSim(const FilePairType& file_pair) const {
    auto first_filename = file_pair.first->filename;
    auto second_filename = file_pair.second->filename;

    cv::Mat first_image = cv::imread(first_filename, CV_LOAD_IMAGE_COLOR);
    if (!first_image.data) {
        return 0.0;
    }
    cv::Mat second_image = cv::imread(second_filename, CV_LOAD_IMAGE_COLOR);
    if (!second_image.data) {
        return 0.0;
    }
    cv::Mat first_image_hsv;
    cv::Mat second_image_hsv;

    cv::cvtColor(first_image, first_image_hsv, cv::COLOR_BGR2HSV);
    cv::cvtColor(second_image, second_image_hsv, cv::COLOR_BGR2HSV);

    // Using 30 bins for hue and 32 for saturation
    int h_bins = 30; int s_bins = 32;
    int histSize[] = { h_bins, s_bins };

    // hue varies from 0 to 256, saturation from 0 to 180
    float s_ranges[] = { 0, 256 };
    float h_ranges[] = { 0, 180 };

    const float* ranges[] = { h_ranges, s_ranges };

    // Use the o-th and 1-st channels
    int channels[] = { 0, 1 };

    cv::MatND first_hist;
    cv::MatND second_hist;

    calcHist(&first_image_hsv, 1, channels, cv::Mat(), first_hist, 2, histSize, ranges, true, false);
    normalize(first_hist, first_hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    calcHist(&second_image_hsv, 1, channels, cv::Mat(), second_hist, 2, histSize, ranges, true, false);
    normalize(second_hist, second_hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

    return compareHist(first_hist, second_hist, 0);
}
